from datetime import datetime

import system
from my_io.block import Block, LOG_FILE_LOCATION
from loguru import logger
from my_io.setting import *
from tools.validater import *
import pickle
from tools.validater import block_index_valdate


class Disk(object):

    @classmethod
    def load_disk(cls):
        """
        加载磁盘
        :return: 磁盘对象
        """
        if os.path.exists(DISK_FILE_LOCATION):
            logger.info("扫描到磁盘文件,加载")
            with open(DISK_FILE_LOCATION, "rb") as f:
                return True, pickle.load(f)
        else:
            logger.info("未扫描到存在磁盘文件,开始创建并初始化")
            return False, Disk()

    @classmethod
    def dump_disk(cls, disk):
        with open(DISK_FILE_LOCATION, "wb") as f:
            pickle.dump(disk, f)

    def __init__(self):
        logger.remove()
        f = open(LOG_FILE_LOCATION, "w", encoding="utf-8")
        logger.add(sink=f)
        # 磁盘
        self.disk = [Block(BLOCK_SIZE) for i in range(BLOCK_NUM)]
        # 位图
        self.bitmap = [0 for i in range(BLOCK_NUM)]
        for i in range(SUPER_BLOCK_SIZE):
            self.bitmap[i] = 1
        # Inode节点
        self.unused_inodes = [system.file_system.Inode() for i in range(INODE_NUM)]
        # inode占两个块
        index = 0
        for i in range(2):
            block = self.get_block_by_index(i)
            inodes = []
            for j in range(index, int(BLOCK_SIZE / INODE_SIZE)):
                if j < len(self.unused_inodes):
                    inodes.append(self.unused_inodes[j])
            index += int(BLOCK_SIZE / INODE_SIZE)
            block.write_content(inodes, INODE_SIZE * len(inodes))
        self.used_inodes = []
        self.root = None
        self.mount_root()

    def mount_root(self):
        # 挂载根目录
        root_inode = self.get_new_inode()
        block_index = 3
        root_inode.file_block_index.append(block_index)
        root_inode.file_type = DIR
        root_inode.file_create_time = datetime.now()
        root_inode.file_own = "root"
        root_inode.file_own_permission = READ_AND_WRITE
        root_inode.file_other_permission = ONLY_READ
        root_inode.file_size = 0
        self.root = system.file_system.Directory("/", root_inode)
        block = self.get_block_by_index(2)
        block.write_content(self.root, 4)

    def get_new_inode(self):
        if len(self.unused_inodes) > 0:
            inode = self.unused_inodes.pop()
            self.used_inodes.append(inode)
            return inode
        else:
            print("no enough inode to create file!")
            return None

    def get_new_block_index(self):
        """
        在磁盘中申请新的文件块
        :return: 新文件块索引,如果无则返回-1
        """
        for i in range(len(self.bitmap)):
            if self.bitmap[i] == 0:
                self.bitmap[i] = 1
                return i
        return -1

    def get_block_by_index(self, index):
        """
        通过索引获取块
        :param index: 索引
        :return: 块对象，如果越界则返回None
        """
        if block_index_valdate(index):
            return self.disk[index]
        else:
            return None

    def init_block_by_index(self, index):
        self.get_block_by_index(index).init()
        self.bitmap[index] = 0

    def release_inode(self, inode):
        self.used_inodes.remove(inode)
        inode.file_block_index = []
        inode.file_type = None
        inode.file_size = None
        inode.file_own = None
        inode.file_other_permission = None
        inode.file_own_permission = None
        inode.file_create_time = None
        self.unused_inodes.append(inode)
